package com.xinz.protocal.serialization;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Method;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;

import com.xinz.protocal.Buffer;
import com.xinz.protocal.Serializer;
import com.xinz.protocal.Session;
import com.xinz.protocal.server.NativeMethod;
import com.xinz.serialization.ByteArrayOutputStream;

public class ZipJavaSerializer implements Serializer{

	@Override
	public Object parseReturn(Session session, Buffer result,
			Object[] responseHeader) throws Throwable {
		ZipInputStream zis = new ZipInputStream(result.asInputStream());
		zis.getNextEntry();
		try {
			ObjectInputStream is = new ObjectInputStream(zis);
			responseHeader[0] = is.readObject();
			boolean isException = is.readBoolean();
			Object obj = is.readObject();
			if(isException){
				throw (Throwable)obj;
			}else{
				return obj;
			}
		} catch (Exception e) {
			e.printStackTrace();
			throw e;
		}finally{
			zis.close();
		}
	}

	@Override
	public Buffer methodToBuffer(Session session, Method method, Object header,
			Object[] args) throws IOException {
		// 从共享上下文里获取方法的ID
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		String methodName = method.getName();
		String interfaceName = method.getDeclaringClass().getName();
		ObjectOutputStream bos = new ObjectOutputStream(baos);
		int id = session.getRemoteMethodId(interfaceName,methodName);
		
		try {
			if(id < 0){
				id = session.saveRemoteMethod(method);
				bos.writeShort(-1);
				bos.writeShort(id);
				bos.writeUTF(interfaceName);
				bos.writeUTF(methodName);
			}else{
				bos.writeShort(id);
			}
			bos.writeObject(header);
			bos.writeObject(args);
		} catch (Exception e) {
			throw new RuntimeException(e.getMessage());
		}
		return baos.toBuffer();
	}

	@Override
	public NativeMethod parseMethod(Session session, Buffer request) {
		try {
			ObjectInputStream is = new ObjectInputStream(request.asInputStream());
			int index = is.readShort();
			Method method;
			
			if(index < 0){
				int id = is.readShort();
				String interfaceName = is.readUTF();
				String methodName = is.readUTF();
				int saveId = session.saveNativeMethod(interfaceName,methodName);
				assert id==saveId:"读取方法：";
				method = session.getNativeMethod(interfaceName,methodName);
			}else{
				method = session.getNativeMethod(index);
			}
			Object header = is.readObject();
			Object args[] = (Object[]) is.readObject();
			return new NativeMethod(method, args, header);
		} catch (Exception e) {
			e.printStackTrace();
			throw new RuntimeException(e.getMessage());
		}
	}

	@Override
	public Buffer returnToBuffer(Session session, Object header, Object result,
			boolean isException) {
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		ZipOutputStream zos = new ZipOutputStream(baos);
		try {
			ObjectOutputStream bos = new ObjectOutputStream(zos);
			zos.putNextEntry(new ZipEntry("z"));
			bos.writeObject(header);
			bos.writeBoolean(isException);
			bos.writeObject(result);
		} catch (Exception e) {
			throw new Error(e.getMessage());
		}finally{
			try {
				zos.close();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		
		return baos.toBuffer();
	}

}
